﻿using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;

namespace Xc.DataAccess.Protocoals.WaterMeters.Models
{
    public abstract class MeterFrameTx
    {
        public const byte StartConst = 0x68;
        public const byte StopConst = 0x16;
        /// <summary>
        /// 起始位
        /// </summary>
        [JsonIgnore] 
        internal byte Start => StartConst;
        /// <summary>
        /// 表计类型
        /// </summary>
        [JsonIgnore] 
        public MeterType MeterType { get;internal protected set; }
        /// <summary>
        /// 表地址
        /// </summary>
        [JsonIgnore] 
        protected abstract ReadOnlySequence<byte> MeterAddress { get;  }
        /// <summary>
        /// 控制码
        /// </summary>
        [JsonIgnore]
        internal protected abstract FrameCommand Cmd { get;  }
        /// <summary>
        /// 数据包长度
        /// </summary>
        [JsonIgnore] 
        internal byte Length => (byte)DataArea.ToSequence(DataArea).Length;
        /// <summary>
        /// 数据域
        /// </summary>
        [JsonIgnore] 
        protected abstract DataArea DataArea { get; }
        /// <summary>
        /// 校验码
        /// </summary>
        [JsonIgnore]
        
        internal byte Check 
        {
            get
            {
                List<byte> vs = new List<byte>();
                vs.Add(Start);
                vs.Add((byte)MeterType);
                vs.AddRange(MeterAddress.ToArray());
                vs.Add((byte)Cmd);
                vs.Add(Length);
                vs.AddRange(DataArea.ToSequence(DataArea).ToArray());
                return (byte)vs.Sum(p => p);
            }
        }
        /// <summary>
        /// 结束包
        /// </summary>
        [JsonIgnore] 
        internal byte Stop => StopConst;
        /// <summary>
        /// 完整包
        /// </summary>
        [JsonIgnore]
        public ReadOnlySpan<byte> FullFrame
        {
            get
            {
                List<byte> vs = new List<byte>();
                vs.Add(Start);
                vs.Add((byte)MeterType);
                vs.AddRange(MeterAddress.ToArray());
                vs.Add((byte)Cmd);
                vs.Add(Length);
                vs.AddRange(DataArea.ToSequence(DataArea).ToArray());
                vs.Add((byte)Check);
                vs.Add((byte)Stop);
                return vs.ToArray();
            }
        }
    }
}
